#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <sys/poll.h>
#include <vector>
#include <string>
#include <dirent.h>

//#include <iconv.h>

#include "common.h"

extern SystemParam *pgSystemParam;

static int sock[MAX_WINDOWS_SERVER_IP_NUM];
static unsigned char indexs[MAX_WINDOWS_SERVER_IP_NUM];
static std::vector<struct dirEnt> m_file_list[MAX_WINDOWS_SERVER_IP_NUM];
	
static int GetCurrentDirList(std::string cur_dir,std::vector<struct dirEnt> &m_dir_list) ;
static void* TcpClientThread(void *arg);

static unsigned char pickOutUsbDiskNum();
static void changeRealDir(char *realDir);

static int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen);
static int u2g(char *inbuf,unsigned int inlen,char *outbuf,unsigned int outlen);
static int g2u(char *inbuf,unsigned int inlen,char *outbuf,unsigned int outlen);

int tcpClientInit()
{
		/*pthread_t ptID;	
		for(unsigned char i = 0; i < MAX_WINDOWS_SERVER_IP_NUM; i ++)
		{
				indexs[i] = i;
				sock[i] = -1;
				if( pthread_create(&ptID, NULL, TcpClientThread, (void *)(indexs + i)) != 0 )
				{
						printf("create thread failure {%s(%d)}\n",__FILE__,__LINE__);		
						return -10 - i;
				} 
		}*/
		
		return 0;
}

static void *TcpClientThread (void *arg)
{
		unsigned char ipIndex = *((unsigned char *)arg);
		printf("ipIndex = %d {%s,%d}\n", ipIndex, __FILE__,__LINE__);
		printf("pgSystemParam->windowsServerIp[%d] = %s\n", ipIndex,pgSystemParam->windowsServerIp[ipIndex]);
	
		int ret;
		socklen_t svrlen;
		struct pollfd pollflag;			
		unsigned char recvbuf[2048];
		unsigned char sendbuf[256*257];	

		char *deviceID;
		char *devicePasswd;
		unsigned char idLen = 0;
		unsigned char passwdLen = 0;

		while( !IsExit() )
		{	
				if( ( sock[ipIndex] = connectTo(pgSystemParam->windowsServerIp[ipIndex],9410,5) ) < 0 )
				{
						if(strlen(pgSystemParam->windowsServerIp[ipIndex]) > 6)	//1.1.1.1
						{
								//printf("connectTo error! sock[%d] = %d\n", ipIndex,sock[ipIndex]);	
								//printf("pgSystemParam->windowsServerIp[%d] = %s\n", ipIndex,pgSystemParam->windowsServerIp[ipIndex]);
						}
						sleep(2);
						continue;
				}
				char cpu[256];
				printf("connectTo %s:9410 success \n", pgSystemParam->windowsServerIp[ipIndex]);
				strcpy(cpu,"FFQ");
				memcpy(sendbuf,cpu,3);
				
				getDeviceIdAndPassWordInfo(&deviceID, idLen, &devicePasswd, passwdLen);
				memcpy(cpu, deviceID, strlen(deviceID) + 1);	
				memcpy(&sendbuf[3],cpu,strlen(cpu) + 1);
				
				memcpy(cpu,pgSystemParam->deviceName, strlen(pgSystemParam->deviceName) + 1);
				memcpy(&sendbuf[3+256],cpu,strlen(cpu) + 1);
				
				//strcpy(cpu,"/mnt/usb_storage");
				changeRealDir(cpu);
				
				memcpy(&sendbuf[3+256+256],cpu,strlen(cpu)+1);
				ret = SendData(sock[ipIndex],(char*)sendbuf,3+256+256+1024,5);
				if(ret < 0)
				{
						printf("send cpucode failure!}\n");
						continue;	
				}
				printf("send cpucode %s!\n",cpu);
				while( !IsExit() )
				{
						if(pgSystemParam->restartUsbClientConnect[ipIndex])
						{
								char logBuf[128];
								sprintf(logBuf, "preapare to restart TcpClientThread ! ipIndex = %d\n", ipIndex);
								LOGD(logBuf);	
								pgSystemParam->restartUsbClientConnect[ipIndex] = false;
								break;
						} 
					
					  pollflag.fd      = sock[ipIndex];
					  pollflag.events  = POLLIN;
					  pollflag.revents = 0;	
					  
					  ret = poll( &pollflag, 1, 5000 );	
				
						if(ret < 0)
						{
							printf("poll error ret [%d]\n",ret);
							break;	
						}
						if( ret == 0 ) 
						{
								continue;
						}	
						
						if( !(pollflag.revents) )	 
						{
							  printf("poll error ret [%d]\n",ret);
								continue;
						}	
						
						ret = RecvData(sock[ipIndex], (char*)recvbuf,2048, 5);
						//test begin
						//char test[1024];
						//memcpy(test,recvbuf,ret);
						printf("-----------------------------usbClient recv[%s]\n",recvbuf);                    
						//test end	
						if( ret == 0 )
						{
								printf("RecvData error ret [%d]\n",ret);
								break;
						}
						if( ret < 0 )
						{
								printf("RecvData error ret [%d]\n",ret);
								break;
						}
						if( recvbuf[0] == 'F')
						{
							if(recvbuf[1] == 'E' ) 
							{
								  static char dirBuf[1024] = {'\0'};
								  static char dirOrgBuf[1024];
								  
								  memcpy(dirOrgBuf,&recvbuf[3],1024);
								  //int ret = g2u(dirOrgBuf,strlen(dirOrgBuf),dirBuf,1024);
								  int ret = -1;
								  if(ret < 0) strcpy(dirBuf, dirOrgBuf);
								  printf("org:%s,real:%s\n", dirOrgBuf,dirBuf);
								  
									ret = GetCurrentDirList(std::string(dirBuf),m_file_list[ipIndex]);
									if(ret < 0)
									{
											printf("open dir error ret=%d\n", ret);
											/*if(access(filename, 0) == 0)
								 	 	{
								  	
								  	}*/
								  		if(strcmp(dirBuf,cpu) == 0)
								  		{
								  				
								  		}
											continue;
									}
									int len =  257*(m_file_list[ipIndex].size());
									printf("GetCurrentDirList len [%d]\n",len);
									sendbuf[0] = 'F';
									sendbuf[1] = 'E';
									sendbuf[2] = 'A';
									sendbuf[3] = len/256;
									sendbuf[4] = len%256;
									for(int i = 0;i < m_file_list[ipIndex].size();++i)
									{
										memcpy(&sendbuf[5+i*257],&m_file_list[ipIndex].at(i),257);	
										printf("memcpy i [%d]\n",i);
									}
									ret = SendData(sock[ipIndex],(char*)sendbuf,5+len,5);
									if(ret < 0)
									{
											printf("SendData error ret [%d]\n",ret);
											continue;
									}
									printf("SendData ret [%d]\n",ret);
									
							}
							if(recvbuf[1] == 'D')
							{
									char dirBuf[1024];
								  memcpy(dirBuf,&recvbuf[3],1024);
									long retlong = GetFileSizeAndSend(dirBuf, ipIndex);
									if(0L > retlong)
									{
											printf("SendData error retlong [%ld]\n",retlong);
											continue;
									}
									printf("SendDataretlong [%ld],sizeof(unsigned long)=[%ld]}\n",retlong,sizeof(unsigned long));
							}
						}	
		
				}
		
				close(sock[ipIndex]);	
		}
		
		return NULL;
}

static int GetCurrentDirList(std::string cur_dir,std::vector<struct dirEnt> &m_dir_list) 
{
	DIR *dirptr = NULL;
	struct stat sta;
	struct dirent *entry;
	int count = 0;
	struct dirEnt bmp;
	m_dir_list.clear();
	if((dirptr = opendir(cur_dir.c_str())) == NULL)
	{
		printf("open dir error ![%s] [%d] failure!\n",cur_dir.c_str(), cur_dir.length());
		return -1;
	}
	else
	{
		while(entry = readdir(dirptr))
		{
			if(strcmp(entry->d_name,".") ==0 || strcmp(entry->d_name,"..") ==0)
			{
				continue;	
			}
			
        std::string allpath = cur_dir + "//";
        allpath += std::string(entry->d_name);
 
			int res = stat(allpath.c_str(), &sta);
    	if(res != 0)
    	{
        printf("stat file fail!\n");

        printf("%d\n", errno);
    	}
    	if(S_ISDIR(sta.st_mode)) 
    	{
    			bmp.d_type = 4;
        	printf("Dir: %s\n", entry->d_name);
    	}
    	else 
    	{
    			bmp.d_type = 8;
       	 printf("File: %s\n", entry->d_name);
    	}
			strcpy(bmp.d_name ,entry->d_name);
			printf("%s\n", bmp.d_name);
			m_dir_list.push_back(bmp);
			++count;
		}
		closedir(dirptr);
	}
	return count;		
}

long GetFileSizeAndSend(char *file_name, int ipIndex)
{
	FILE *fp;
	if((fp=fopen(file_name,"rb+")) == NULL)	
	{
		printf("Open file %s failed!\n", file_name);
		return (long)(-1);
	}
	if(fseek(fp,0L, SEEK_END))
	{
			printf("fseek（） function failed!\n");
			fclose(fp);
			return (long)(-2);
	}
	long file_byte_size=ftell(fp);
	printf("GetFileSizeAndSend file_byte_size[%ld] success!\n",file_byte_size);
	int ret;
	long num = (long)(0);
	long nCount = (long)(0);	
	//rewind(fp);
	if(fseek(fp,0L, SEEK_SET))
	{
			printf("fseek（） function failed!\n");
			fclose(fp);
			return (long)(-3);
	}
	/*
	fclose(fp);
	if((fp=fopen(file_name,"rb+")) == NULL)	
	{
		printf("Open file %s failed!\n", file_name);
		return (long)(-1);
	}*/
	unsigned char sendBuf[2096];
	char readBuf[2096];
	sendBuf[0] = 'F';
	sendBuf[1] = 'D';
	sendBuf[2] = 'A';
	
	//if(sizeof(long) == 8)
	//{
	//		sendBuf[3] = file_byte_size >> 56;
	//		sendBuf[4] = file_byte_size >> 48;
	//		sendBuf[5] = file_byte_size >> 40;
	//		sendBuf[6] = file_byte_size >> 32;
	//}
	//else
	//{
			sendBuf[3] = 0;
			sendBuf[4] = 0;
			sendBuf[5] = 0;
			sendBuf[6] = 0;
	//}

	sendBuf[7] = file_byte_size >> 24;
	sendBuf[8] = file_byte_size >> 16;
	sendBuf[9] = file_byte_size >> 8;
	sendBuf[10] = file_byte_size;
	ret = SendData( sock[ipIndex], (char*)sendBuf, 11, 5 );				
			
	if( ret <= 0 )
	{
		printf("SendData failed ret[%d]!\n",ret);
			fclose(fp);
		return ( long)(-4);
	}			
	do
	{
				/*if(fseeko64(fp,num, SEEK_SET))
				{
					printf("fseek（） function failed!\n");
					fclose(fp);
					return (-1);
				}*/
				//fseek(fp,num, SEEK_SET);
				
				num = (file_byte_size - nCount) > 2096 ? 2096 : (file_byte_size - nCount);
				//printf("GetFileSizeAndSend num[%ld] file_byte_size[%ld]success!}\n",num,file_byte_size);
				ret = fread(readBuf,(int)num,1,fp);
				if(ret < 0)
				{
					fclose(fp);
					return (long)(-5);	
				}
				memcpy(sendBuf,readBuf,num);
				ret = SendData( sock[ipIndex], (char*)sendBuf, (int)num, 15);				
			
				if( ret != (int)num )
				{
						printf("SendData ret[%d] send[%d] failure!}\n",ret,(int)num);
						fclose(fp);
						return (long)(-6);
				}			
					
				nCount += ret;	
				printf("GetFileSizeAndSend nCount[%ld] success!}\n",nCount);
	}
	while( nCount <  file_byte_size );
	fclose(fp);
	printf("GetFileSizeAndSend file_byte_size[%ld] success!\n",file_byte_size);
	return file_byte_size;
}

static unsigned char pickOutUsbDiskNum()
{
		char cur_dir[] = "/mnt/usb_disk_1";
		unsigned char dirLen = strlen(cur_dir);
		struct dirent *entry;
		DIR *dirptr = NULL;
		
		for(unsigned char i = 1; i <= 4; i++)
		{
				cur_dir[dirLen - 1] = i + '0';
				if((dirptr = opendir(cur_dir)) == NULL)
				{
						printf("pickOutUsbDiskNum: error 1 cur_dir = %s\n", cur_dir);
				}
				else
				{
						while(entry = readdir(dirptr))
						{
								if(strcmp(entry->d_name,".") ==0 || strcmp(entry->d_name,"..") ==0)
								{
										continue;	
								}
								
								return i;
						}
				}
		}
		
		return 1;
}

static void changeRealDir(char *realDir)
{
		if(!realDir) return;
	
		unsigned char realDisk = pickOutUsbDiskNum();
		sprintf(realDir, "/mnt/usb_disk_%d", realDisk);
		
		printf("changeRealDir: realDir=%s\n", realDir);
}

static int code_convert(const char *from_charset,const char *to_charset,char *inbuf,unsigned int inlen,char *outbuf,unsigned int outlen)
{
		/*iconv_t cd;
		int rc;
		char **pin = &inbuf;
		char **pout = &outbuf;

		cd = iconv_open(to_charset,from_charset);
		if (cd==0) return -1;
		memset(outbuf,0,outlen);
		if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
		iconv_close(cd);*/
		return 0;
}

//UNICODE码转为GB2312码
static int u2g(char *inbuf,unsigned int inlen,char *outbuf,unsigned int outlen)
{
		return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}

//GB2312码转为UNICODE码
static int g2u(char *inbuf,unsigned int inlen,char *outbuf,unsigned int outlen)
{
		return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}
